package by.grsu.crs.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import by.grsu.crs.dao.OrderDao;
import by.grsu.crs.dao.PaymentDao;
import by.grsu.crs.dao.StatusDao;
import by.grsu.crs.model.Order;
import by.grsu.crs.model.Payment;
import by.grsu.crs.model.Status;

public class PaymentDaoImpl implements PaymentDao {
	private static final String INSERT_NEW_PAYMENT 
		= "INSERT INTO payments(oid, notice, total, sid) VALUES (?, ?, ?, ?)";

	private static final String SELECT_ALL_PAYMENTS 
		= "SELECT id, oid, notice, total, sid FROM payments";
	
	private static final String SELECT_PAYMENT_BY_ID
		= "SELECT id, oid, notice, total, sid FROM payments WHERE id = ?";
	
	private static final String DELETE_PAYMENT_BY_ID 
		= "DELETE FROM payments WHERE id = ?;";
	
	private static final String UPDATE_PAYMENT_BY_ID 
		= "UPDATE payments SET oid = ?, notice = ?, total = ?, sid = ? WHERE id = ?";
	
	private Connection dbConnection;
	private PreparedStatement preparedStatement = null;
	private ResultSet resultSet = null;
	
	public PaymentDaoImpl(Connection dbConnection) {
		this.dbConnection = dbConnection;
	}
	
	public boolean addPayment(Payment payment) throws SQLException {
		try {
			preparedStatement = dbConnection.prepareStatement(INSERT_NEW_PAYMENT);
			preparedStatement.setInt(1, payment.getOrder().getId());
			preparedStatement.setString(2, payment.getNotice());
			preparedStatement.setInt(3, payment.getTotal());
			preparedStatement.setInt(4, payment.getStatus().getId());
			if (preparedStatement.executeUpdate() == 1) {
				return true;
			}
		} catch(Exception e) {
			//TODO: log this
			e.printStackTrace();
		} finally {
			preparedStatement.close();
		}
		
		return false;
	}
	
	public List<Payment> getAllPayments() throws SQLException {
		List<Payment> payments = new ArrayList<Payment>();
		OrderDao orderDao = new OrderDaoImpl(dbConnection);
		StatusDao statusDao = new StatusDaoImpl(dbConnection);
		
		try {		
			preparedStatement = dbConnection.prepareStatement(SELECT_ALL_PAYMENTS);
			resultSet = preparedStatement.executeQuery();
			
			while (resultSet.next()) {
				payments.add(new Payment(resultSet.getInt("id"),
						orderDao.getOrderById(resultSet.getInt("oid")),
						resultSet.getString("notice"),
						resultSet.getInt("total"),
						statusDao.getStatusById(resultSet.getInt("sid"))));
			}
		} catch(Exception e) {
			//TODO: log this
			e.printStackTrace();
		} finally {
			resultSet.close();
			preparedStatement.close();
		}
		
		return payments;
	}
	
	public Payment getPaymentById(int id) throws SQLException {
		Payment payment = null;
		OrderDao orderDao = new OrderDaoImpl(dbConnection);
		StatusDao statusDao = new StatusDaoImpl(dbConnection);
		
		try {		
			preparedStatement = dbConnection.prepareStatement(SELECT_PAYMENT_BY_ID);
			preparedStatement.setInt(1, id);
			resultSet = preparedStatement.executeQuery();
			
			resultSet.last();			
			if(resultSet.getRow() != 0) {
				resultSet.first();
				
				Order order = orderDao.getOrderById(resultSet.getInt("oid"));
				String notice = resultSet.getString("notice");
				int total = resultSet.getInt("total");
				Status status = statusDao.getStatusById(resultSet.getInt("sid"));
				
				payment = new Payment(order, notice, total, status);
			}		
		} catch(Exception e) {
			//TODO: log this.
			e.printStackTrace();
		} finally {
			resultSet.close();
			preparedStatement.close();
		}
		
		return payment;
	}
	
	public boolean deletePaymentByID(int id) throws SQLException {		
		try {
			preparedStatement = dbConnection.prepareStatement(DELETE_PAYMENT_BY_ID);
			preparedStatement.setInt(1, id);
			if (preparedStatement.executeUpdate() == 1) {
				return true;
			}
		} catch(Exception e) {
			//TODO: log this.
			e.printStackTrace();
		} finally {
			preparedStatement.close();
		}
		
		return false;
	}
	
	public boolean updatePaymentById(int id, Payment payment) throws SQLException {
		try {
			preparedStatement = dbConnection.prepareStatement(UPDATE_PAYMENT_BY_ID);
			preparedStatement.setInt(1, payment.getOrder().getId());
			preparedStatement.setString(2, payment.getNotice());
			preparedStatement.setInt(3, payment.getTotal());
			preparedStatement.setInt(4, payment.getStatus().getId());
			if (preparedStatement.executeUpdate() == 1) {
				return true;
			}
		} catch(Exception e) {
			//TODO: log this.
			e.printStackTrace();
		} finally {
			preparedStatement.close();
		}
		
		return false;
	}
}
